/* verilator lint_off UNUSEDSIGNAL */

import "DPI-C" function void get_cpu_pc(
	input int pc,
	input int dnpc
);

import "DPI-C" function void get_cpu_inst(
	input int inst
);



`include "DEFWIDTH.v"

module WB_STAGE(
    input clk,
    input reset,
    //allowin
    output wb_allowin,
    //from mem
    input mem_to_wb_valid,
    input [`MEM_TO_WB_BUS_WD -1:0] mem_to_wb_bus,
	//to mem
	output [`WB_TO_MEM_BRBUS_WD -1:0] wb_to_mem_brbus,

    //to id
    output [`WB_TO_ID_RFBUS_WD -1:0] wb_to_id_rfbus,
	output [`WB_TO_ID_CFBUS_WD -1:0] wb_to_id_cfbus,
	

    //debug
    output [31:0] debug_wb_pc,
    output        debug_wb_rf_wen,
    output [4:0]  debug_wb_rf_waddr,
    output [31:0] debug_wb_rf_wdata,
	
	//bypass
    output [`WB_TO_ID_BYPASS_WD -1:0] wb_to_id_bypass,
    output [4:0] wb_to_id_rdbypass,
    output       wb_to_id_rfwenbypass,
	output [`WB_TO_ID_CFBYPASS_WD -1:0] wb_to_id_cfbypass,
    output [11:0] wb_to_id_csrbypass,
    output       wb_to_id_cfwenbypass,

	output       wb_to_mem_brjmpbypass

);
reg wb_valid;
wire wb_ready_go,wb_flush;


reg [`MEM_TO_WB_BUS_WD -1:0] mem_to_wb_bus_r;

wire        dst_writeback,dst_writeback_csr;
wire [ 4:0] rd;
wire [11:0] csr;
wire [31:0] rs1;
wire [31:0] writeback_result;
wire        wb_ebreak,wb_ecall;
wire [31:0] debug_wb_dnpc,debug_wb_inst,wb_tvec;

//WB1,输入
assign wb_ready_go = 1'b1;
assign wb_flush = 1'b0;
assign wb_allowin = !wb_valid || wb_ready_go;//非阻塞的条件变了
always @(posedge clk) begin
    if(reset) begin
        wb_valid <= 1'b0;
    end else if(wb_allowin) begin
        wb_valid <= mem_to_wb_valid;
    end

    if(wb_allowin && mem_to_wb_valid) begin
        mem_to_wb_bus_r <= mem_to_wb_bus;
    end else begin
		mem_to_wb_bus_r <= 'b0;
	end

	get_cpu_pc(debug_wb_pc,debug_wb_dnpc);
	get_cpu_inst(debug_wb_inst);

end

assign {
	dst_writeback,
	dst_writeback_csr,
	debug_wb_inst,
	csr,
	rs1,
    rd,
    writeback_result,
    debug_wb_pc,
	debug_wb_dnpc,
    wb_ebreak,
	wb_ecall,
	wb_tvec
} = mem_to_wb_bus_r[`MEM_TO_WB_BUS_WD -1 :0];

//WB-ebreak
ebreak wb_eb(
    .clk(clk),
    .reset(reset),
    .flag(wb_ebreak)
);

//WB2,输入

//rf
wire wen;
wire [4:0] waddr;
wire [31:0] wdata;
assign wen = dst_writeback && wb_valid;
assign waddr = rd;
assign wdata = writeback_result;

assign wb_to_id_rfbus = {
    wen, //1
    waddr, //5
    wdata //32
};

//cf
wire cwen;
wire [11:0] cwaddr;
wire [31:0] cwdata;
assign cwen = dst_writeback_csr && wb_valid;
assign cwaddr = csr;
assign cwdata = rs1;
assign wb_to_id_cfbus = {
    cwen, //1
    cwaddr, //12
    cwdata //32
};



//WB3,输出
assign wb_to_id_bypass = wdata;
assign wb_to_id_rdbypass = waddr;
assign wb_to_id_rfwenbypass = wen;
assign wb_to_id_cfbypass = cwdata;
assign wb_to_id_csrbypass = cwaddr;
assign wb_to_id_cfwenbypass = cwen;



//debug
assign debug_wb_rf_wen = wen;
assign debug_wb_rf_waddr = waddr;
assign debug_wb_rf_wdata = wdata;

assign wb_to_mem_brjmpbypass = wb_ecall;
assign wb_to_mem_brbus =  wb_tvec;

endmodule
